package sbc.ejb3.dao;

import java.util.List;

import javax.annotation.Resource;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.ObjectMessage;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.jms.Topic;
import javax.jms.TopicConnection;
import javax.jms.TopicConnectionFactory;
import javax.jms.TopicPublisher;
import javax.jms.TopicSession;

import org.apache.log4j.Logger;

import sbc.ejb3.Platine;
import sbc.ejb3.Sensor;

@Stateless
public class Distributor implements DistributorRemote {
	
	private static Logger log = Logger.getLogger(Distributor.class);
	
	@EJB private PlatineRemote platineRemote;			
	@EJB private SensorRemote sensorRemote;
	
	@Resource(mappedName="TopicConnectionFactory")
	private TopicConnectionFactory topicConnectionFactory;
	
	@Resource(mappedName="QueueConnectionFactory")
	private QueueConnectionFactory queueConnectionFactory;
	
	@Resource(mappedName="topic/qsTopic")
	private Topic qsTopic;
	
	@Resource(mappedName="topic/montageTopic")
	private Topic montageTopic;
	
	@Resource(mappedName="queue/logisticQueue")
	private Queue logisticQueue;
	

	public void forwardToMontageTopic() {
		log.info("forwardToMontageTopic");
		
		/*
		 * check for gemesseneSensoren and unmontiertePlatinen
		 * possibly forward to montageTopic
		 */
		List<Sensor> gemesseneSensoren = sensorRemote.getGemesseneSensoren();
        for (Sensor s : gemesseneSensoren)	
        	log.info("Gemessener Sensor: " + s);
        
		List<Platine> unmontiertePlatinen = platineRemote.getUnmontiertePlatinen();
        for (Platine p : unmontiertePlatinen)	
        	log.info("Unmontierte Platine: " + p);
        
        if (gemesseneSensoren.size() >= 2 && unmontiertePlatinen.size() >= 1) {
        	int montageIterations = 0;
        	if (unmontiertePlatinen.size() < gemesseneSensoren.size() / 2) {
        		montageIterations = unmontiertePlatinen.size();
        	}
        	else {
        		montageIterations = gemesseneSensoren.size() / 2;
        	}
        	log.info("montageIterations: " + montageIterations);
        	
        	for (int i=0; i < montageIterations; i++) {
	        	try {
					log.info("forwarding platine and 2x sensor to montageTopic");

					Platine platine = unmontiertePlatinen.get(i);
					Sensor sensor1  = gemesseneSensoren.get(2*i);
					Sensor sensor2  = gemesseneSensoren.get(2*i+1);
					log.info("platine: " + platine);
					log.info("sensor1: " + sensor1);
					log.info("sensor2: " + sensor2);
					
					log.info("Creating connection");
					TopicConnection connection = topicConnectionFactory.createTopicConnection();
	
					try {
						log.info("Creating session");
						TopicSession session = connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
						
						log.info("Creating publisher");
						TopicPublisher sender = session.createPublisher(montageTopic);
	
						log.info("Creating message");					
						MapMessage mapMessage = session.createMapMessage();
						mapMessage.setInt("PlatineId", platine.getId());
						mapMessage.setInt("Sensor1Id", sensor1.getId());
						mapMessage.setInt("Sensor2Id", sensor2.getId());
						
						log.info("Sending message");
						sender.send(mapMessage);
					}
					finally {
						connection.close();
					}
				} 
	        	catch (JMSException e) {
					e.printStackTrace();
				}        
        	}
        }		
	}

	public void forwardToQsTopic() {
		log.info("forwardToQsTopic");
		
		/*
		 * check for ungemesseneSensoren
		 * possibly forward to qsTopic
		 */
		List<Sensor> ungemesseneSensoren = sensorRemote.getUngemesseneSensoren();
        for (Sensor s : ungemesseneSensoren) {
        	log.info("Ungemessener Sensor: " + s);
        
        	try {
				log.info("forwarding sensor to qsTopic");
				
				log.info("Creating connection");
				TopicConnection connection = topicConnectionFactory.createTopicConnection();

				try {
					log.info("Creating session");
					TopicSession session = connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
					
					log.info("Creating publisher");
					TopicPublisher sender = session.createPublisher(qsTopic);

					log.info("Creating message");					
					ObjectMessage topicObjectMessage = session.createObjectMessage(s);

					log.info("Sending message");
					sender.send(topicObjectMessage);
				}
				finally {
					connection.close();
				}
			} 
        	catch (JMSException e) {
				e.printStackTrace();
			}        
        }
	}

	public void forwardToLogisticQueue() {
		log.info("forwardToLogisticQueue");
		
		/*
		 * check for montiertePlatinen
		 * possibly forward to logisticQueue
		 */
		List<Platine> montiertePlatinen = platineRemote.getMontiertePlatinen();
        for (Platine p : montiertePlatinen) {
        	log.info("Montierte Platinen: " + p);
        
			try {
				log.info("Creating connection");
				QueueConnection connection = queueConnectionFactory.createQueueConnection();
				
				try {
					log.info("Creating session");
					QueueSession session = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
	
					log.info("Creating sender");
					QueueSender sender = session.createSender(logisticQueue);
	
					log.info("Starting connection");
					connection.start();
	
					log.info("Creating message");
					ObjectMessage objectMessage = session.createObjectMessage(p);
	
					log.info("Sending message");
					sender.send(objectMessage);
				} 
				finally {
					connection.close();
				}
			} 
			catch (JMSException e) {
				e.printStackTrace();
			}		
		}
	}

}
